#include "native/java/lang/Object.hpp"
#include "rtda/heap/object.h"
#include "rtda/heap/class.h"
#include "rtda/heap/class_loader.h"

namespace jvm {
    namespace lang {

        const std::string ObjectNative::JL_OBJECT = "java/lang/Object";

        void ObjectNative::getClass(std::shared_ptr<rtda::Frame> pframe) {
            auto thisObj = pframe->getLocalVars().getThis();
            auto&& pclass = thisObj->getClass().lock();
            if (!pclass)
            {
                LOG_ERROR("null pointer!");
                throw std::runtime_error("null pointer!");
            }
            auto clazz = pclass->getJClass();
            pframe->getOperandStack()->pushRef(clazz);
        }

        void ObjectNative::hashCode(std::shared_ptr<rtda::Frame> pframe) {
            auto thisObj = pframe->getLocalVars().getThis();
            auto hash = static_cast<int32_t>(reinterpret_cast<uintptr_t>(thisObj));
            //auto hash = static_cast<int32_t>(reinterpret_cast<uintptr_t>(thisObj.get()));
            pframe->getOperandStack()->pushInt(hash);
        }

        void ObjectNative::clone(std::shared_ptr<rtda::Frame> pframe) {
            auto thisObj = pframe->getLocalVars().getThis();
            auto&& pclass = thisObj->getClass().lock();
            if (!pclass)
            {
                LOG_ERROR("null pointer!");
                throw std::runtime_error("null pointer!");
            }

            auto cloneable = pclass->getLoder()->loadClass("java/lang/Cloneable");

            if (!pclass->isImplements(cloneable)) {
                LOG_ERROR("CloneNotSupportedException");
                throw std::runtime_error("java.lang.CloneNotSupportedException");
            }

            pframe->getOperandStack()->pushRef(thisObj->clone());
        }

    } // namespace lang
} // namespace jvm